技巧42 清理容器

Docker新手经常抱怨的一点便是,在短时间内,用户可能在系统上残留许多不同状态的容器,而且没有一个标准工具通过命令行管理这些容器。

问题

想要清理系统上的残留容器。

解决方案

设置一个别名来执行清理旧容器的命令。这里最简单的办法是删除所有容器。显然,这是一个有风险的方案,只应在确定这是预期行为的时候使用。下列命令将会删除宿主机上的所有容器。

$ docker ps -a -q | \  ⇽--- 获取所有容器ID的列表,包括正在运行的以及已停止的,然后将它们传给……
 xargs --no-run-if-empty docker rm -f  ⇽--- ……docker rm -f命令,被传入的任意容器将会被删除,即使它们还处于运行状态

简单介绍一下 xargs 命令,它会获取输入的每一行内容,并将它们全部作为参数传递给后续命令。为了防止报错,我们这里传入了一个额外参数 --no-run-if-empty ,这可以避免在前面的命令完全没有输出的情况下执行该命令。

如果有正在运行的容器想要保留,但是又想删除所有已经退出的容器,那么不妨过滤一下 docker ps 命令返回的条目:

docker ps -a -q --filter status=exited | \  ⇽--- --filter标志会告知docker ps命令想要返回的容器。在这种情况下限制成状态为已经退出的那些容器。也可以选择处于正在运行中或者正在重启状态的容器
 xargs --no-run-if-empty docker rm  ⇽--- 这次不用再强行删除容器,因为根据给定的过滤参数,它们本身就不应该处于运行状态

事实上,删掉所有已停止的容器是一个很常见的用例,为此Docker专门添加了一条命令: docker container prune 。然而,这条命令仅限于该用例,要进行任何更复杂的操作,仍然需要回过头来参考本技巧里介绍的命令。

作为更高级用例的示范,下列命令将会列出所有返回非零错误码的容器。如果系统上有许多容器,用户想要自动检查并删除那些异常退出的任意容器,就可能需要这样做:

comm -3 \  ⇽--- 执行comm命令来比较两个文件内容的差异。加上-3 参数将不会显示同时出现在两个文件里的行内容(这些容器的退出码都是0),然后输出其他不同的部分
 <(docker ps -a -q --filter=status=exited | sort) \  ⇽--- 找出退出的容器 ID,给它们排序,然后以文件形式传给comm
<(docker ps -a -q --filter=exited=0 | sort) | \  ⇽--- 找出退出码为0的容器,给它们排序,然后以文件形式传给comm
 xargs --no-run-if-empty docker inspect > error_containers  ⇽--- 对非0退出码(comm命令管道的输出)的容器执行docker inspect,并将输出结果保存到error_containers文件中

提示

也许你还没看到过这种用法,bash里的 <(command) 语法被称为进程替换。它允许把一个命令的输出结果作为文件,传给其他命令,这在无法使用管道输出的时候非常有用。

上述示例相对比较复杂,但是它展示了将不同的工具命令组合在一起的威力。它会输出所有已停止的容器的ID,然后挑出那些非0退出码的容器(即那些以异常方式退出的容器)。如果读者还在努力理解这个用法,不妨先单独执行每条命令,然后理解它们的含义,这样有助于了解整个过程。

像这样的命令可以用来在生产环境里采集容器信息。用户可能想要对它做些调整,改为执行一个cron定时任务来清除正常退出的容器。

将单行代码包装成命令

可以给命令设置别名,以便在登录到宿主机后更容易操作。为了达成这一点,需要在~/.bashrc文件里添加如下代码:

alias dockernuke='docker ps -a -q | \
xargs --no-run-if-empty docker rm -f'

然后,在下一次登录时,从命令行执行 dockernuke ,将删除在系统上找到的任何Docker容器。

我们发现这样做节省的时间是相当可观的。但是要小心!这种方式同样也非常容易误删生产环境的容器,我们可以证明。即使足够小心,不去删除正在运行的容器,仍然可能会误删那些没有运行但仍然有用的纯数据容器。

讨论

本书介绍到的许多技巧的最终目的都是创建容器,尤其是在技巧76介绍到的Docker Compose以及有关编排的章节里——毕竟,编排都是关于如何管理多个容器的。用户也许会发现这里讨论到的命令用于清理机器(本地或远程)很有价值,在完成每个技巧后可以获得一个全新的环境。

results matching ""

    No results matching ""